/*
 * Copyright (c) 2012 by Paweł Lebioda <pawel.lebioda89@gmail.com>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef _ENC28J60_H
#define _ENC28J60_H

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>

#include "../arch/spi.h"

#include "enc28j60_config.h"

#define ENC28J60_RST_ON()	ENC28J60_RST_PORT &= ~(1<<ENC28J60_RST);
#define ENC28J60_RST_OFF()	ENC28J60_RST_PORT |= (1<<ENC28J60_RST);
#define ENC28J60_CS_ACTIVE()	ENC28J60_CS_PORT &= ~(1<<ENC28J60_CS)
#define ENC28J60_CS_INACTIVE()	ENC28J60_CS_PORT |=	(1<<ENC28J60_CS)

void enc28j60_io_init(void);
void enc28j60_reset(void);
void enc28j60_clear_bits(uint8_t address,uint8_t bits);
void enc28j60_set_bits(uint8_t address,uint8_t bits);
void enc28j60_init(const uint8_t * macaddr);
void enc28j60_spi_init(void);
uint8_t	enc28j60_read_op(uint8_t op,uint8_t addr);
void enc28j60_write_op(uint8_t op,uint8_t addr,uint8_t data);
void enc28j60_read_buffer(uint16_t len,uint8_t * data);
void enc28j60_write_buffer(uint16_t len,uint8_t * data);
void enc28j60_set_bank(uint8_t addr);
uint8_t	enc28j60_read(uint8_t addr);
void enc28j60_write(uint8_t addr,uint8_t data);
void enc28j60_phy_write(uint8_t addr,uint16_t data);
uint8_t	enc28j60_send_packet(uint8_t * buff,uint16_t len);
uint16_t enc28j60_receive_packet(uint8_t * buff,uint16_t max_len);
uint8_t	enc28j60_get_revision(void);

//SPI Instruction Set
#define ENC28J60_OPC_RCR	0x00		//Read Control Register
#define ENC28J60_OPC_RBM	0x3A		//Read Buffer Memory
#define ENC28J60_OPC_WCR	0x40		//Write Control Register
#define ENC28J60_OPC_WBM	0x7A		//Write Buffer Memory
#define ENC28J60_OPC_BFS	0x80		//Bit Field Set
#define ENC28J60_OPC_BFC	0xA0		//Bit Field Clear
#define ENC28J60_OPC_RES	0xFF		//System Command (Soft Reset)

// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
// buffer boundaries applied to internal 8K ram
// the entire available packet buffer space is allocated
//
// start with recbuf at 0/
#define ENC28J60_RXSTART_INIT	0x0
// receive buffer end
#define ENC28J60_RXSTOP_INIT	(0x1FFF-0x0600-1)
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
#define ENC28J60_TXSTART_INIT	(0x1FFF-0x0600)
// stp TX buffer at end of mem
#define ENC28J60_TXSTOP_INIT	0x1FFF
//
// max frame length which the conroller will accept:
#define	MAX_FRAMELEN		 1518		// maximum ethernet frame length
#define ENC28J60_MAX_FRAMELEN	 MAX_FRAMELEN


#define ENC28J60_ADDR_MASK	0x1F
#define ENC28J60_BANK_MASK	0x60
#define ENC28J60_SPRD_MASK	0x80
// All-bank registers
#define EIE			0x1B
#define EIR			0x1C
#define ESTAT			0x1D
#define ECON2			0x1E
#define ECON1			0x1F
// Bank 0 registers
#define ERDPTL			(0x00|0x00)
#define ERDPTH			(0x01|0x00)
#define EWRPTL			(0x02|0x00)
#define EWRPTH			(0x03|0x00)
#define ETXSTL			(0x04|0x00)
#define ETXSTH			(0x05|0x00)
#define ETXNDL			(0x06|0x00)
#define ETXNDH			(0x07|0x00)
#define ERXSTL			(0x08|0x00)
#define ERXSTH			(0x09|0x00)
#define ERXNDL			(0x0A|0x00)
#define ERXNDH			(0x0B|0x00)
#define ERXRDPTL		(0x0C|0x00)
#define ERXRDPTH		(0x0D|0x00)
#define ERXWRPTL		(0x0E|0x00)
#define ERXWRPTH		(0x0F|0x00)
#define EDMASTL			(0x10|0x00)
#define EDMASTH			(0x11|0x00)
#define EDMANDL			(0x12|0x00)
#define EDMANDH			(0x13|0x00)
#define EDMADSTL		(0x14|0x00)
#define EDMADSTH		(0x15|0x00)
#define EDMACSL			(0x16|0x00)
#define EDMACSH			(0x17|0x00)
// Bank 1 registers
#define EHT0			(0x00|0x20)
#define EHT1			(0x01|0x20)
#define EHT2			(0x02|0x20)
#define EHT3			(0x03|0x20)
#define EHT4			(0x04|0x20)
#define EHT5			(0x05|0x20)
#define EHT6			(0x06|0x20)
#define EHT7			(0x07|0x20)
#define EPMM0			(0x08|0x20)
#define EPMM1			(0x09|0x20)
#define EPMM2			(0x0A|0x20)
#define EPMM3			(0x0B|0x20)
#define EPMM4			(0x0C|0x20)
#define EPMM5			(0x0D|0x20)
#define EPMM6			(0x0E|0x20)
#define EPMM7			(0x0F|0x20)
#define EPMCSL			(0x10|0x20)
#define EPMCSH			(0x11|0x20)
#define EPMOL			(0x14|0x20)
#define EPMOH			(0x15|0x20)
#define EWOLIE			(0x16|0x20)
#define EWOLIR			(0x17|0x20)
#define ERXFCON			(0x18|0x20)
#define EPKTCNT			(0x19|0x20)
// Bank 2 registers
#define MACON1			(0x00|0x40|0x80)
#define MACON2			(0x01|0x40|0x80)
#define MACON3			(0x02|0x40|0x80)
#define MACON4			(0x03|0x40|0x80)
#define MABBIPG			(0x04|0x40|0x80)
#define MAIPGL			(0x06|0x40|0x80)
#define MAIPGH			(0x07|0x40|0x80)
#define MACLCON1		(0x08|0x40|0x80)
#define MACLCON2		(0x09|0x40|0x80)
#define MAMXFLL			(0x0A|0x40|0x80)
#define MAMXFLH			(0x0B|0x40|0x80)
#define MAPHSUP			(0x0D|0x40|0x80)
#define MICON			(0x11|0x40|0x80)
#define MICMD			(0x12|0x40|0x80)
#define MIREGADR		(0x14|0x40|0x80)
#define MIWRL			(0x16|0x40|0x80)
#define MIWRH			(0x17|0x40|0x80)
#define MIRDL			(0x18|0x40|0x80)
#define MIRDH			(0x19|0x40|0x80)
// Bank 3 registers
#define MAADR1			(0x00|0x60|0x80)
#define MAADR0			(0x01|0x60|0x80)
#define MAADR3			(0x02|0x60|0x80)
#define MAADR2			(0x03|0x60|0x80)
#define MAADR5			(0x04|0x60|0x80)
#define MAADR4			(0x05|0x60|0x80)
#define EBSTSD			(0x06|0x60)
#define EBSTCON			(0x07|0x60)
#define EBSTCSL			(0x08|0x60)
#define EBSTCSH			(0x09|0x60)
#define MISTAT			(0x0A|0x60|0x80)
#define EREVID			(0x12|0x60)
#define ECOCON			(0x15|0x60)
#define EFLOCON			(0x17|0x60)
#define EPAUSL			(0x18|0x60)
#define EPAUSH			(0x19|0x60)
// PHY registers
#define PHCON1			0x00
#define PHSTAT1			0x01
#define PHHID1			0x02
#define PHHID2			0x03
#define PHCON2			0x10
#define PHSTAT2			0x11
#define PHIE			0x12
#define PHIR			0x13
#define PHLCON			0x14

// ENC28J60 ERXFCON Register Bit Definitions
#define ERXFCON_UCEN		0x80
#define ERXFCON_ANDOR		0x40
#define ERXFCON_CRCEN		0x20
#define ERXFCON_PMEN		0x10
#define ERXFCON_MPEN		0x08
#define ERXFCON_HTEN		0x04
#define ERXFCON_MCEN		0x02
#define ERXFCON_BCEN		0x01
// ENC28J60 EIE Register Bit Definitions
#define EIE_INTIE		0x80
#define EIE_PKTIE		0x40
#define EIE_DMAIE		0x20
#define EIE_LINKIE		0x10
#define EIE_TXIE		0x08
#define EIE_WOLIE		0x04
#define EIE_TXERIE		0x02
#define EIE_RXERIE		0x01
// ENC28J60 EIR Register Bit Definitions
#define EIR_PKTIF		0x40
#define EIR_DMAIF		0x20
#define EIR_LINKIF		0x10
#define EIR_TXIF		0x08
#define EIR_WOLIF		0x04
#define EIR_TXERIF		0x02
#define EIR_RXERIF		0x01
// ENC28J60 ESTAT Register Bit Definitions
#define ESTAT_INT		0x80
#define ESTAT_LATECOL		0x10
#define ESTAT_RXBUSY		0x04
#define ESTAT_TXABRT		0x02
#define ESTAT_CLKRDY		0x01
// ENC28J60 ECON2 Register Bit Definitions
#define ECON2_AUTOINC		0x80
#define ECON2_PKTDEC		0x40
#define ECON2_PWRSV		0x20
#define ECON2_VRPS		0x08
// ENC28J60 ECON1 Register Bit Definitions
#define ECON1_TXRST		0x80
#define ECON1_RXRST		0x40
#define ECON1_DMAST		0x20
#define ECON1_CSUMEN		0x10
#define ECON1_TXRTS		0x08
#define ECON1_RXEN		0x04
#define ECON1_BSEL1		0x02
#define ECON1_BSEL0		0x01
// ENC28J60 MACON1 Register Bit Definitions
#define MACON1_LOOPBK		0x10
#define MACON1_TXPAUS		0x08
#define MACON1_RXPAUS		0x04
#define MACON1_PASSALL	 	0x02
#define MACON1_MARXEN		0x01
// ENC28J60 MACON2 Register Bit Definitions
#define MACON2_MARST		0x80
#define MACON2_RNDRST		0x40
#define MACON2_MARXRST	 	0x08
#define MACON2_RFUNRST	 	0x04
#define MACON2_MATXRST	 	0x02
#define MACON2_TFUNRST	 	0x01
// ENC28J60 MACON3 Register Bit Definitions
#define MACON3_PADCFG2	 	0x80
#define MACON3_PADCFG1	 	0x40
#define MACON3_PADCFG0	 	0x20
#define MACON3_TXCRCEN	 	0x10
#define MACON3_PHDRLEN	 	0x08
#define MACON3_HFRMLEN	 	0x04
#define MACON3_FRMLNEN	 	0x02
#define MACON3_FULDPX		0x01
// ENC28J60 MICMD Register Bit Definitions
#define MICMD_MIISCAN		0x02
#define MICMD_MIIRD		0x01
// ENC28J60 MISTAT Register Bit Definitions
#define MISTAT_NVALID		0x04
#define MISTAT_SCAN		0x02
#define MISTAT_BUSY		0x01
// ENC28J60 PHY PHCON1 Register Bit Definitions
#define PHCON1_PRST		0x8000
#define PHCON1_PLOOPBK	 	0x4000
#define PHCON1_PPWRSV		0x0800
#define PHCON1_PDPXMD		0x0100
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
#define PHSTAT1_PFDPX		0x1000
#define PHSTAT1_PHDPX		0x0800
#define PHSTAT1_LLSTAT	 	0x0004
#define PHSTAT1_JBSTAT	 	0x0002
// ENC28J60 PHY PHCON2 Register Bit Definitions
#define PHCON2_FRCLINK	 	0x4000
#define PHCON2_TXDIS		0x2000
#define PHCON2_JABBER		0x0400
#define PHCON2_HDLDIS		0x0100

// ENC28J60 Packet Control Byte Bit Definitions
#define PKTCTRL_PHUGEEN		0x08
#define PKTCTRL_PPADEN	 	0x04
#define PKTCTRL_PCRCEN	 	0x02
#define PKTCTRL_POVERRIDE 	0x01
//PHIE - PHY interrupt enable registers
#define PHIE_PLNKIE		4	//PHY Link Change Interrupt Enable bit
#define PHIE_PGEIE		1	//PHY Global Interrupt Enable bit
// PHLCON - PHY module LED control register
#define PHLCON_STRCH		1
#define PHLCON_STRCH_TIME	2
#define PHLCON_LEDB		4
#define PHLCON_LEDA		8

#define PHLCON_STRCH_TIME_139MS	2
#define PHLCON_STRCH_TIME_73MS	1
#define PHLCON_STRCH_TIME_40MS	0

#define PHLCON_LED_TA		1	// display transmit activity (strechable)
#define PHLCON_LED_RA		2	// display receive activity (strechable)
#define PHLCON_LED_COL		3	// display collision activity (strechable)
#define PHLCON_LED_LS		4	// display link status
#define PHLCON_LED_DS		5 	// dispaly duplex status
#define PHLCON_LED_TRA		7 	// dispaly transmit and receive activity (strechable)
#define PHLCON_LED_ON		8 	// On
#define PHLCON_LED_OFF		9 	// Off
#define PHLCON_LED_BLINK_FAST	10 	// blink fast
#define PHLCON_LED_BLINK_SLOW	11 	// blink slow
#define PHLCON_LED_LS_RA	12 	// display link status and receive activity (always streched)
#define PHLCON_LED_LS_TRA	13 	// display link status and transmit/receive activity (always streched)
#define PHLCON_LED_DS_COL	14	// display duplex status and collision activity



#endif //_ENC28J60_h
